////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include "SmegPlaceable.hpp"

#include <SFML/Graphics.hpp>

#include <SmegCore/Math/Math.hpp>

SmegPlaceable::SmegPlaceable() :
    m_XCoordinateSelected( OPACITY_NOT_SELECTED ),
    m_YCoordinateSelected( OPACITY_NOT_SELECTED ),
    m_XYCoordinateSelected( OPACITY_NOT_SELECTED ),
    m_RotationCoordinateSelected( OPACITY_NOT_SELECTED ),
    m_eMode( eMode_Translation ),
    m_eDraggingType( eDrag_None ),
    m_LastDragPos()
{
}

SmegPlaceable::eDragEnum SmegPlaceable::BeginDragSelection( const sf::Vector2f& _MouseBeginDrag ) {
    m_LastDragPos = _MouseBeginDrag;
    m_fCurrentAngle = getRotation();
    m_eDraggingType = SetSelection(m_LastDragPos);

    return m_eDraggingType;
}

void SmegPlaceable::DragSelection( const sf::Vector2f& _MouseDrag ) {
    sf::Vector2f moveVec(_MouseDrag - m_LastDragPos);
    
    switch (m_eDraggingType) {
    case eDrag_None:
        // Begginning of dragging was out of SmegPlaceable, so just color the object
        SetSelection( _MouseDrag );
        break;
    case eDrag_Translation_X:
        m_XCoordinateSelected = OPACITY_SELECTED;
        move( moveVec.x, 0.0f );
        break;
    case eDrag_Translation_Y:
        m_YCoordinateSelected = OPACITY_SELECTED;
        move( 0.0f, moveVec.y );
        break;
    case eDrag_Translation_ALL:
        m_XYCoordinateSelected = OPACITY_SELECTED;
        move( moveVec.x, moveVec.y );
        break;
    case eDrag_Rotation:
        m_RotationCoordinateSelected = OPACITY_SELECTED;
        rotate( moveVec.x + moveVec.y );
        break;
    }

    m_LastDragPos = _MouseDrag;
}

void SmegPlaceable::StopDragSelection() {
    m_eDraggingType = eDrag_None;
}

SmegPlaceable::eDragEnum SmegPlaceable::SetSelection( const sf::Vector2f& _MousePos ) {
    m_XCoordinateSelected = OPACITY_NOT_SELECTED;
    m_YCoordinateSelected = OPACITY_NOT_SELECTED;
    m_XYCoordinateSelected = OPACITY_NOT_SELECTED;
    m_RotationCoordinateSelected = OPACITY_NOT_SELECTED;

    sf::Vector2f PosToMouse(_MousePos - getPosition());
    
    if ( eMode_Translation == m_eMode ) {
        if ( PosToMouse.x >= 0 && PosToMouse.x <= COORDINATE_SIZE &&
            PosToMouse.y >= -COORDINATE_HALF_WIDTH && PosToMouse.y <= COORDINATE_HALF_WIDTH) {
            m_XCoordinateSelected = OPACITY_SELECTED;

            return eDrag_Translation_X;
        } else if ( PosToMouse.y >= 0 && PosToMouse.y <= COORDINATE_SIZE &&
            PosToMouse.x >= -COORDINATE_HALF_WIDTH && PosToMouse.x <= COORDINATE_HALF_WIDTH ) {
            m_YCoordinateSelected = OPACITY_SELECTED;

            return eDrag_Translation_Y;
        } else if ( PosToMouse.x >= 0 && PosToMouse.x <= SQUARE_COORDINATE_SIZE &&
            PosToMouse.y >= 0 && PosToMouse.y <= SQUARE_COORDINATE_SIZE ) {
            m_XYCoordinateSelected = OPACITY_SELECTED;

            return eDrag_Translation_ALL;
        }
    } else if ( eMode_Rotation == m_eMode ) {
        float sqrLgth = smeg::math::SquaredLength( PosToMouse );

        if ( sqrLgth >= SQR_MIN_ROTATION_SIZE && sqrLgth <= SQR_MAX_ROTATION_SIZE) {
            m_RotationCoordinateSelected = OPACITY_SELECTED;

            return eDrag_Rotation;
        }
    }

    return eDrag_None;
}

void SmegPlaceable::ResetSelection() {
    m_XCoordinateSelected = OPACITY_NOT_SELECTED;
    m_YCoordinateSelected = OPACITY_NOT_SELECTED;
    m_XYCoordinateSelected = OPACITY_NOT_SELECTED;
    m_RotationCoordinateSelected = OPACITY_NOT_SELECTED;
}

void SmegPlaceable::draw(sf::RenderTarget& target, sf::RenderStates states) const
{
    states.transform *= getTransform();

    if ( eMode_Translation == m_eMode ) {
        // X coordinates
        sf::RectangleShape rectangleX( sf::Vector2f( 100.0f, 5.0f ) );
        rectangleX.setFillColor(sf::Color(255, 0, 0, m_XCoordinateSelected));
        /*
        sf::Vertex lineX[] =
        {
            sf::Vertex(sf::Vector2f( 0.0f, 0.0f ), sf::Color( 255, 0, 0, m_XCoordinateSelected )),
            sf::Vertex(sf::Vector2f( 100.0f, 0.0f ), sf::Color( 255, 0, 0, m_XCoordinateSelected ))
        };
        */

        // Y coordinates
        sf::RectangleShape rectangleY( sf::Vector2f( 5.0f, 100.0f ) );
        rectangleY.setFillColor(sf::Color(0, 255, 0, m_YCoordinateSelected));
        /*
        sf::Vertex lineY[] =
        {
            sf::Vertex(sf::Vector2f( 0.0f, 0.0f ), sf::Color( 0, 255, 0, m_YCoordinateSelected )),
            sf::Vertex(sf::Vector2f( 0.0f, 100.0f ), sf::Color( 0, 255, 0, m_YCoordinateSelected ))
        };
        */

        // X & Y coordinates
        sf::RectangleShape rectangle( sf::Vector2f( 50.0f, 50.0f ) );
        rectangle.setFillColor(sf::Color(255, 255, 0, m_XYCoordinateSelected));
        
        target.draw(rectangle, states);
        target.draw(rectangleX, states);
        target.draw(rectangleY, states);
        /*
        target.draw(lineX, 2, sf::Lines, states);
        target.draw(lineY, 2, sf::Lines, states);
        */
    } else if ( eMode_Rotation == m_eMode ) {
        if ( eDrag_Rotation == m_eDraggingType ) {
            float angleBegin = m_fCurrentAngle - getRotation();

            angleBegin = smeg::math::GetValidDegreeAngle( angleBegin ) * smeg::math::DEG_TO_RAD;

            // Draw in yellow the changing angle
            // First line (beginning of angle)
            sf::Vertex beginLine[] =
            {
                sf::Vertex(sf::Vector2f( 0.0f, 0.0f ), sf::Color( 255, 255, 0 )),
                sf::Vertex(sf::Vector2f( 50.0f * cos( angleBegin ), 50.0f * sin( angleBegin ) ), sf::Color( 255, 255, 0 )),
            };

            // Second line (end of angle)
            sf::Vertex endLine[] =
            {
                sf::Vertex(sf::Vector2f( 0.0f, 0.0f ), sf::Color( 255, 255, 0 )),
                sf::Vertex(sf::Vector2f( 50.0f, 0.0f ), sf::Color( 255, 255, 0 )),
            };

            sf::VertexArray selected(sf::TrianglesFan, 32);
            float fInc = -angleBegin / 30.0f, // We forget the first and second vertex
                fCurAngle = angleBegin;
            selected[0].position.x = 0.0f;
            selected[0].position.y = 0.0f;
            selected[0].color = sf::Color( 255, 255, 0, 120 );
            for ( unsigned i = 1; i < 32; ++i ) {
                selected[i].position.x = 50.0f * cos( fCurAngle );
                selected[i].position.y = 50.0f * sin( fCurAngle );
                selected[i].color = sf::Color( 255, 255, 0, 120 );

                fCurAngle += fInc;
            }

            target.draw(selected, states);
            target.draw(beginLine, 2, sf::Lines, states);
            target.draw(endLine, 2, sf::Lines, states);
        }

        sf::CircleShape circle( 50.0f );
        circle.setFillColor( sf::Color::Transparent );
        circle.setOutlineThickness( 10.0f );
        circle.setOutlineColor( sf::Color( 0, 0, 255, m_RotationCoordinateSelected ) );
        circle.setPosition( -50.0f, -50.0f );

        target.draw( circle, states );
    }
}
